package com.zdxf.controller;

import com.zdxf.conf.Constant;
import com.zdxf.domain.UserDO;
import com.zdxf.event.UserLoginEvent;
import com.zdxf.service.impl.LoginServiceImpl;
import com.zdxf.util.Json;
import com.zdxf.util.RSA;
import com.zdxf.util.Result;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpHeaders;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

@Api(tags = "登录接口")
@RestController
@RequestMapping("/login")
public class LoginController {
    @Autowired
    LoginServiceImpl loginService;

    @Autowired
    private ApplicationEventPublisher publisher;

    @Value("${jwt.secret}")
    private String secret;


    Result result = Constant.RESULT_EMPTY;
    HashMap<String, Object> params = new HashMap<>(Constant.HASH_MAP_SIZE);

    @ApiOperation(value = "登录", notes = "登录")
    @ResponseBody()
    @PostMapping(value = "/auth")
    public void selectTouristGenderList(@RequestBody UserDO body, HttpServletResponse response) throws Exception {
        params.put("username", body.getUsername());
        params.put("password", RSA.decryptByPrivateKey(body.getPassword()));
        result = loginService.login(params);
        // log
        publisher.publishEvent(new UserLoginEvent(this, "用户登录", body.getUsername()));
        Json.toJson(result, response);
    }

    @PreAuthorize("hasAnyRole('USER')")
    @PostMapping(value = "/testNeed")
    public Result testNeed() {
        return new Result(true, 20000, "成功", "testNeed");

    }

    @PostMapping(value = "/testNotNeed")
    public Result testNotNeed() {
        return new Result(true, 20000, "成功", "testNotNeed");

    }
//    @GetMapping("haha")
//    public Result haha(){
//        UserDetails userDetails = (UserDetails) org.springframework.security.core.context.SecurityContextHolder.getContext().getAuthentication().getPrincipal();
//        String str="haha:"+userDetails.getUsername()+","+userDetails.getPassword();
//        return new Result(true, 20000, "成功", str);
//    }

    @ApiOperation(value = "退出登录", notes = "退出登录")
    @ResponseBody()
    @PostMapping(value = "/logout")
    public void logout(@RequestHeader HttpHeaders headers, HttpServletResponse response) throws Exception {
        String token = headers.get("Authorization").get(0).substring(7);
        long expiration = 0;
        String username = "";
        try {
            expiration = getAllClaimsFromToken(token).getExpiration().getTime();
            username = (String) getAllClaimsFromToken(token).get("sub");
        } catch (Exception e) {
            e.printStackTrace();
            expiration = 0;
            username = "";
        }
        params.put("token", token);
        params.put("expiration", expiration);
        params.put("username", username);
        result = loginService.logout(params);
        // log
        publisher.publishEvent(new UserLoginEvent(this, "用户退出登录", username));
        Json.toJson(result, response);
    }

    public Claims getAllClaimsFromToken(String token) {
        return Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token)
                .getBody();
    }

    @ApiOperation(value = "更新token", notes = "使用登录返回的refreshToken去换取新token")
    @ResponseBody()
    @PostMapping(value = "/refresh")
    public void refresh(@RequestHeader HttpHeaders headers, HttpServletResponse response) throws Exception {
        String token = headers.get("Authorization").get(0).substring(7);
        String username = (String) getAllClaimsFromToken(token).get("sub");
        params.put("username", username);
        result = loginService.refresh(params);
        // log
        publisher.publishEvent(new UserLoginEvent(this, "用户更新token", username));
        Json.toJson(result, response);
    }
}
